/* eslint-disable */
export module MathUtil {
  export function generateUUID() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      const r = (Math.random() * 16) | 0,
        v = c === 'x' ? r : (r & 0x3) | 0x8;
      return v.toString(16);
    });
  }

  /** 随机生成一个在[min, max)之间的随机数 */
  export function randomBetween(min: number, max: number) {
    return min + Math.random() * (max - min);
  }

  /** 随机生成一个整数，范围为[min, max) */
  export function randomIntegerBetween(min: number, max: number) {
    return Math.floor(this.randomBetween(min, max));
  }

  /** 随机生成一个整数，范围为[min, max) */
  export function randomIntegerBetweenByString(range: number[]) {
    return Math.floor(this.randomBetween(range[0], range[1]));
  }

  /** 随机生成n个不重复的整数，范围为[n, m]，x为生成个数 */
  export function randomUniqueIntegers(n: number, m: number, x: number): number[] {
    if (x > m - n + 1) {
      return Array.from({ length: m - n + 1 }, (_, i) => n + i);
    }

    const range = Array.from({ length: m - n + 1 }, (_, i) => n + i);
    const result: number[] = [];

    for (let i = 0; i < x; i++) {
      const randomIndex = Math.floor(Math.random() * (range.length - i)) + i;
      [range[i], range[randomIndex]] = [range[randomIndex], range[i]];
      result.push(range[i]);
    }

    return result;
  }

  /** 随机生成一个不重复的整数，范围为[n, m]，x为排除的整数 */
  export function randomIntegerExceptX(n: number, m: number, x: number): number {
    if (n > m || (n === m && n === x)) {
      return n;
    }

    let result: number;
    do {
      result = Math.floor(Math.random() * (m - n + 1)) + n;
    } while (result === x);

    return result;
  }

  /** 随机生成x个整数，范围为[n, m] */
  export function randomNumbers(n: number, m: number, x: number): number[] {
    if (n == m) {
      return Array.from({ length: x }, () => n);
    }
    if (n > m) {
      [n, m] = [m, n];
    }
    const range = m - n + 1;
    const arr = Array.from({ length: x }, () => Math.floor(Math.random() * range + n));
    return arr;
  }

  /** 打乱数据 */
  export function shuffleArr<T>(array: T[]): T[] {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
  }

  /** 快速开方 */
  export function fastSqrt(number: number, tolerance: number = 1e-7): number {
    if (number < 0) {
      throw new Error('MathUtil:fastSqrt() error： 不能对负数开方');
    }
    if (number === 0 || number === 1) {
      return number;
    }

    let guess = number / 2;
    while (true) {
      const nextGuess = (guess + number / guess) / 2;
      if (Math.abs(nextGuess - guess) < tolerance) {
        return nextGuess;
      }
      guess = nextGuess;
    }
  }

  export function UUID() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      const r = (Math.random() * 16) | 0,
        v = c === 'x' ? r : (r & 0x3) | 0x8;
      return v.toString(16);
    });
  }

  export function shortUUID(): string {
    return 'xx4xxyxx'.replace(/[xy]/g, function (c) {
      const r = (Math.random() * 16) | 0,
        v = c === 'x' ? r : (r & 0x3) | 0x8;
      return v.toString(16);
    });
  }

  export function formatNumber(num: number, count: number): number {
    return parseFloat(num.toFixed(count));
  }

  /** 最大公约数 */
  export function gcd(a: number, b: number): number {
    if (b == 0) {
      return a;
    } else {
      return gcd(b, a % b);
    }
  }

  /** 最小公倍数 */
  export function lcm(a: number, b: number): number {
    return Math.abs(a * b) / gcd(a, b);
  }

  /** 保留小数 */
  export function toFixed(num: number, count: number = 0): number {
    const t = Math.pow(10, count);
    const temp = Math.floor(num * t) / t;
    return temp;
  }

  /** 保留小数（四色五入） */
  export function toFixedPro(num: number, count: number = 0): number {
    const t = Math.pow(10, count);
    const temp = Math.round(num * t) / t;
    return temp;
  }
}
